Komplexní průvodce posílením zabezpečení frontendu pomocí Content Security Policy (CSP) a Cross-Origin Resource Sharing (CORS) pro ochranu vašich webových aplikací před moderními hrozbami.
Posílení zabezpečení frontendu: Content Security Policy a CORS
V dnešním propojeném digitálním světě je bezpečnost frontendu naprosto klíčová. Webové aplikace jsou stále častěji cílem sofistikovaných útoků, a proto jsou robustní bezpečnostní opatření nezbytná. Dvěma kritickými součástmi bezpečné frontendové architektury jsou Content Security Policy (CSP) a Cross-Origin Resource Sharing (CORS). Tento komplexní průvodce poskytuje podrobný pohled na tyto technologie a nabízí praktické příklady a užitečné postřehy, které vám pomohou posílit vaše webové aplikace proti moderním hrozbám.
Co je Content Security Policy (CSP)?
Content Security Policy (CSP) je přidaná bezpečnostní vrstva, která pomáhá detekovat a zmírňovat některé typy útoků, včetně útoků Cross-Site Scripting (XSS) a data injection. CSP je implementována tak, že webový server posílá prohlížeči HTTP hlavičku odpovědi Content-Security-Policy. Tato hlavička definuje seznam povolených zdrojů (whitelist), ze kterých může prohlížeč načítat prostředky. Omezením zdrojů obsahu, které může prohlížeč načíst, CSP výrazně ztěžuje útočníkům vložení škodlivého kódu na váš web.
Jak CSP funguje
CSP funguje tak, že instruuje prohlížeč, aby načítal prostředky (např. skripty, styly, obrázky, fonty) pouze ze schválených zdrojů. Tyto zdroje jsou specifikovány v hlavičce CSP pomocí direktiv. Pokud se prohlížeč pokusí načíst prostředek ze zdroje, který není explicitně povolen, zablokuje požadavek a nahlásí porušení.
Direktivy CSP: Komplexní přehled
Direktivy CSP řídí typy prostředků, které lze načítat z konkrétních zdrojů. Zde je přehled některých nejdůležitějších direktiv:
- default-src: Specifikuje výchozí zdroj pro všechny typy obsahu. Jedná se o záložní direktivu, která se použije, pokud nejsou přítomny jiné, specifičtější direktivy.
- script-src: Specifikuje zdroje, ze kterých lze načítat skripty. To je klíčové pro prevenci útoků XSS.
- style-src: Specifikuje zdroje, ze kterých lze načítat styly.
- img-src: Specifikuje zdroje, ze kterých lze načítat obrázky.
- font-src: Specifikuje zdroje, ze kterých lze načítat fonty.
- media-src: Specifikuje zdroje, ze kterých lze načítat audio a video.
- object-src: Specifikuje zdroje, ze kterých lze načítat pluginy (např. Flash). Často se nastavuje na 'none', aby se pluginy zcela zakázaly kvůli jejich inherentním bezpečnostním rizikům.
- frame-src: Specifikuje zdroje, ze kterých lze načítat rámce (např. <iframe>).
- connect-src: Specifikuje URL adresy, ke kterým se může uživatelský agent připojit pomocí skriptovacích rozhraní, jako jsou XMLHttpRequest, WebSocket a EventSource.
- base-uri: Specifikuje URL adresy, které lze použít v elementu <base> dokumentu.
- form-action: Specifikuje URL adresy, na které lze odesílat formuláře.
- upgrade-insecure-requests: Instruuje uživatelského agenta, aby automaticky upgradoval nezabezpečené požadavky (HTTP) na zabezpečené (HTTPS).
- report-uri: Specifikuje URL adresu, kam má prohlížeč posílat hlášení o porušení CSP. Tato direktiva je zastaralá ve prospěch `report-to`.
- report-to: Specifikuje název skupiny pro hlášení definované v hlavičce `Report-To`, kam má prohlížeč posílat hlášení o porušení CSP.
Klíčová slova zdrojového seznamu CSP
V rámci direktiv CSP můžete pro definování povolených zdrojů používat klíčová slova zdrojového seznamu. Zde jsou některá běžná klíčová slova:
- 'self': Povoluje prostředky ze stejného původu (schéma a hostitel) jako dokument.
- 'none': Zakazuje prostředky ze všech zdrojů.
- 'unsafe-inline': Povoluje použití inline skriptů a stylů (např. tagy <script> a atributy style). Používejte s maximální opatrností, protože to výrazně oslabuje ochranu CSP proti XSS.
- 'unsafe-eval': Povoluje použití funkcí pro dynamické vyhodnocování kódu, jako jsou
eval()aFunction(). Používejte s maximální opatrností, protože to přináší značná bezpečnostní rizika. - 'unsafe-hashes': Povoluje specifické inline obsluhy událostí nebo tagy <style>, které odpovídají zadanému hashi. Vyžaduje podporu prohlížeče. Používejte s opatrností.
- 'strict-dynamic': Specifikuje, že důvěra explicitně daná skriptu přítomnému v kódu (doprovázením nonce nebo hashem) se přenese na všechny skripty načtené tímto kořenovým skriptem.
- data: Povoluje data: URI (např. inline obrázky kódované jako base64). Používejte s opatrností.
- https:: Povoluje načítání prostředků přes HTTPS z jakékoli domény.
- [hostname]: Povoluje prostředky z konkrétní domény (např. example.com). Můžete také specifikovat číslo portu (např. example.com:8080).
- [scheme]://[hostname]:[port]: Plně kvalifikované URI, které povoluje prostředky z určeného schématu, hostitele a portu.
Praktické příklady CSP
Podívejme se na několik praktických příkladů hlaviček CSP:
Příklad 1: Základní CSP s 'self'
Tato politika povoluje prostředky pouze ze stejného původu:
Content-Security-Policy: default-src 'self'
Příklad 2: Povolení skriptů z konkrétní domény
Tato politika povoluje skripty z vaší vlastní domény a důvěryhodného CDN:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
Příklad 3: Zakázání inline skriptů a stylů
Tato politika zakazuje inline skripty a styly, což je silná obrana proti XSS:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'
Důležité: Zakázání inline skriptů vyžaduje refaktorizaci vašeho HTML, aby se inline skripty přesunuly do externích souborů.
Příklad 4: Použití nonce pro inline skripty
Pokud musíte použít inline skripty, použijte nonce (kryptograficky náhodné, jednorázové tokeny) k povolení konkrétních bloků inline skriptů. Je to bezpečnější než 'unsafe-inline'. Server musí pro každý požadavek vygenerovat jedinečný nonce a zahrnout ho jak do hlavičky CSP, tak do tagu <script>.
Content-Security-Policy: default-src 'self'; script-src 'nonce-r4nd0mN0nc3'; style-src 'self'
<script nonce="r4nd0mN0nc3"> console.log('Inline script'); </script>
Poznámka: Nezapomeňte pro každý požadavek generovat nový nonce. Nepoužívejte nonce opakovaně!
Příklad 5: Použití hashů pro inline styly
Podobně jako nonce lze hashe použít k povolení konkrétních inline bloků <style>. To se provádí generováním hashe SHA256, SHA384 nebo SHA512 obsahu stylu.
Content-Security-Policy: default-src 'self'; style-src 'sha256-HASHEDSTYLES'
<style sha256="HASHEDSTYLES"> body { background-color: #f0f0f0; } </style>
Poznámka: Hashe jsou méně flexibilní než nonce, protože jakákoli změna obsahu stylu zneplatní hash.
Příklad 6: Hlášení porušení CSP
Pro sledování porušení CSP použijte direktivu report-uri nebo report-to:
Content-Security-Policy: default-src 'self'; report-to csp-endpoint;
Budete také muset nakonfigurovat hlavičku Report-To. Hlavička Report-To definuje jednu nebo více skupin pro hlášení, které specifikují, kam a jak mají být hlášení odesílána.
Report-To: {"group":"csp-endpoint","max_age":10886400,"endpoints":[{"url":"https://example.com/csp-report"}]}
Testování a nasazení CSP
Implementace CSP vyžaduje pečlivé plánování a testování. Začněte s restriktivní politikou a postupně ji uvolňujte podle potřeby. K testování politiky bez blokování prostředků použijte hlavičku Content-Security-Policy-Report-Only. Tato hlavička hlásí porušení, aniž by politiku vynucovala, což vám umožní identifikovat a opravit problémy před nasazením politiky do produkce.
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpoint;
Analyzujte hlášení generovaná prohlížečem, abyste identifikovali jakákoli porušení a podle toho upravili svou politiku. Jakmile jste si jisti, že vaše politika funguje správně, nasaďte ji pomocí hlavičky Content-Security-Policy.
Osvědčené postupy pro CSP
- Začněte s default-src: Vždy definujte
default-src, abyste stanovili základní politiku. - Buďte specifičtí: Používejte specifické direktivy a klíčová slova zdrojového seznamu k omezení rozsahu vaší politiky.
- Vyhněte se 'unsafe-inline' a 'unsafe-eval': Tato klíčová slova výrazně oslabují CSP a je třeba se jim pokud možno vyhnout.
- Používejte nonce nebo hashe pro inline skripty a styly: Pokud musíte použít inline skripty nebo styly, použijte nonce nebo hashe k povolení konkrétních bloků kódu.
- Sledujte porušení CSP: Používejte direktivu
report-urineboreport-toke sledování porušení CSP a podle toho upravujte svou politiku. - Důkladně testujte: Použijte hlavičku
Content-Security-Policy-Report-Onlyk testování vaší politiky před nasazením do produkce. - Iterujte a vylepšujte: CSP není jednorázová konfigurace. Neustále sledujte a vylepšujte svou politiku, abyste se přizpůsobili změnám ve vaší aplikaci a vyvíjejícímu se prostředí hrozeb.
Co je Cross-Origin Resource Sharing (CORS)?
Cross-Origin Resource Sharing (CORS) je mechanismus, který umožňuje webovým stránkám z jednoho původu (domény) přistupovat k prostředkům z jiného původu. Ve výchozím nastavení prohlížeče vynucují Same-Origin Policy, která brání skriptům v provádění požadavků na jiný původ, než ze kterého skript pochází. CORS poskytuje způsob, jak toto omezení selektivně uvolnit, což umožňuje legitimní cross-origin požadavky a zároveň chrání před škodlivými útoky.
Porozumění Same-Origin Policy
Same-Origin Policy je základní bezpečnostní mechanismus, který brání škodlivému skriptu z jedné webové stránky v přístupu k citlivým datům na jiné webové stránce. Původ je definován schématem (protokolem), hostitelem (doménou) a portem. Dvě URL adresy mají stejný původ, pokud a pouze pokud mají stejné schéma, hostitele a port.
Například:
https://www.example.com/app1/index.htmlahttps://www.example.com/app2/index.htmlmají stejný původ.https://www.example.com/index.htmlahttp://www.example.com/index.htmlmají různý původ (různé schéma).https://www.example.com/index.htmlahttps://sub.example.com/index.htmlmají různý původ (různý hostitel).https://www.example.com:8080/index.htmlahttps://www.example.com:80/index.htmlmají různý původ (různý port).
Jak CORS funguje
Když webová stránka provede cross-origin požadavek, prohlížeč nejprve odešle na server „preflight“ požadavek. Preflight požadavek používá metodu HTTP OPTIONS a obsahuje hlavičky, které udávají HTTP metodu a hlavičky, které bude skutečný požadavek používat. Server poté odpoví s hlavičkami, které udávají, zda je cross-origin požadavek povolen.
Pokud server požadavek povolí, zahrne do odpovědi hlavičku Access-Control-Allow-Origin. Tato hlavička specifikuje původ(y), kterým je povolen přístup k prostředku. Prohlížeč poté pokračuje se skutečným požadavkem. Pokud server požadavek nepovolí, nezahrne hlavičku Access-Control-Allow-Origin a prohlížeč požadavek zablokuje.
Hlavičky CORS: Podrobný pohled
CORS se spoléhá na HTTP hlavičky pro komunikaci mezi prohlížečem a serverem. Zde jsou klíčové hlavičky CORS:
- Access-Control-Allow-Origin: Specifikuje původ(y), kterým je povolen přístup k prostředku. Tato hlavička může obsahovat konkrétní původ (např.
https://www.example.com), zástupný znak (*) nebonull. Použití*povoluje požadavky z jakéhokoli původu, což se z bezpečnostních důvodů obecně nedoporučuje. Použitínullje vhodné pouze pro „neprůhledné odpovědi“, například když je prostředek načten pomocí protokolufile://nebo data URI. - Access-Control-Allow-Methods: Specifikuje HTTP metody, které jsou povoleny pro cross-origin požadavek (např.
GET, POST, PUT, DELETE). - Access-Control-Allow-Headers: Specifikuje HTTP hlavičky, které jsou povoleny v cross-origin požadavku. To je důležité pro zpracování vlastních hlaviček.
- Access-Control-Allow-Credentials: Udává, zda má prohlížeč zahrnout pověření (např. cookies, autorizační hlavičky) do cross-origin požadavku. Tato hlavička musí být nastavena na
true, aby bylo povoleno použití pověření. - Access-Control-Expose-Headers: Specifikuje, které hlavičky mohou být zpřístupněny klientovi. Ve výchozím nastavení je zpřístupněna pouze omezená sada hlaviček.
- Access-Control-Max-Age: Specifikuje maximální dobu (v sekundách), po kterou může prohlížeč ukládat preflight požadavek do mezipaměti.
- Origin: Toto je hlavička požadavku odeslaná prohlížečem k označení původu požadavku.
- Vary: Obecná HTTP hlavička, ale důležitá pro CORS. Když je
Access-Control-Allow-Origingenerována dynamicky, měla by být do odpovědi zahrnuta hlavičkaVary: Origin, aby instruovala mechanismy ukládání do mezipaměti, že se odpověď liší v závislosti na hlavičce požadavkuOrigin.
Praktické příklady CORS
Podívejme se na několik praktických příkladů konfigurací CORS:
Příklad 1: Povolení požadavků z konkrétního původu
Tato konfigurace povoluje požadavky pouze z https://www.example.com:
Access-Control-Allow-Origin: https://www.example.com
Příklad 2: Povolení požadavků z jakéhokoli původu (nedoporučuje se)
Tato konfigurace povoluje požadavky z jakéhokoli původu. Používejte s opatrností, protože to může přinést bezpečnostní rizika:
Access-Control-Allow-Origin: *
Příklad 3: Povolení specifických metod a hlaviček
Tato konfigurace povoluje metody GET, POST a PUT a hlavičky Content-Type a Authorization:
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Příklad 4: Povolení pověření
Pro povolení pověření (např. cookies) musíte nastavit Access-Control-Allow-Credentials na true a specifikovat konkrétní původ (nemůžete použít * při povolování pověření):
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Credentials: true
Musíte také nastavit credentials: 'include' ve vašem JavaScriptovém fetch/XMLHttpRequest požadavku.
fetch('https://api.example.com/data', {
credentials: 'include'
})
Preflight požadavky CORS
Pro určité typy cross-origin požadavků (např. požadavky s vlastními hlavičkami nebo jinými metodami než GET, HEAD nebo POST s Content-Type application/x-www-form-urlencoded, multipart/form-data nebo text/plain) odesílá prohlížeč preflight požadavek pomocí metody OPTIONS. Server musí na preflight požadavek odpovědět s příslušnými hlavičkami CORS, aby naznačil, zda je skutečný požadavek povolen.
Zde je příklad preflight požadavku a odpovědi:
Preflight požadavek (OPTIONS):
OPTIONS /data HTTP/1.1
Origin: https://www.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Content-Type, Authorization
Preflight odpověď (200 OK):
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Hlavička Access-Control-Max-Age specifikuje, jak dlouho může prohlížeč ukládat preflight odpověď do mezipaměti, což snižuje počet preflight požadavků.
CORS a JSONP
JSON with Padding (JSONP) je starší technika pro obcházení Same-Origin Policy. JSONP však má značná bezpečnostní rizika a je třeba se mu vyhnout ve prospěch CORS. JSONP se spoléhá na vkládání tagů <script> do stránky, což může spustit libovolný kód. CORS poskytuje bezpečnější a flexibilnější způsob zpracování cross-origin požadavků.
Osvědčené postupy pro CORS
- Vyhněte se použití *: Vyhněte se použití zástupného znaku (*) v hlavičce
Access-Control-Allow-Origin, protože povoluje požadavky z jakéhokoli původu. Místo toho specifikujte konkrétní původ(y), kterým je povolen přístup k prostředku. - Buďte specifičtí s metodami a hlavičkami: Specifikujte přesné HTTP metody a hlavičky, které jsou povoleny v hlavičkách
Access-Control-Allow-MethodsaAccess-Control-Allow-Headers. - Používejte Access-Control-Allow-Credentials s opatrností: Povolte
Access-Control-Allow-Credentialspouze v případě, že potřebujete povolit pověření (např. cookies) v cross-origin požadavcích. Buďte si vědomi bezpečnostních důsledků povolení pověření. - Zabezpečte své preflight požadavky: Ujistěte se, že váš server správně zpracovává preflight požadavky a vrací správné hlavičky CORS.
- Používejte HTTPS: Vždy používejte HTTPS jak pro původ, tak pro prostředky, ke kterým přistupujete napříč původy. To pomáhá chránit před útoky man-in-the-middle.
- Vary: Origin: Pokud dynamicky generujete hlavičku `Access-Control-Allow-Origin`, vždy zahrňte hlavičku `Vary: Origin`, abyste předešli problémům s mezipamětí.
CSP a CORS v praxi: Kombinovaný přístup
Ačkoli CSP i CORS řeší bezpečnostní problémy, fungují na různých vrstvách a poskytují doplňkovou ochranu. CSP se zaměřuje na zabránění prohlížeči v načítání škodlivého obsahu, zatímco CORS se zaměřuje na řízení toho, které původy mohou přistupovat k prostředkům na vašem serveru.
Kombinací CSP a CORS můžete vytvořit robustnější bezpečnostní postoj pro vaše webové aplikace. Například můžete použít CSP k omezení zdrojů, ze kterých lze načítat skripty, a CORS k řízení toho, které původy mohou přistupovat k vašim API koncovým bodům.
Příklad: Zabezpečení API pomocí CSP a CORS
Řekněme, že máte API hostované na https://api.example.com, které chcete zpřístupnit pouze z https://www.example.com. Můžete nakonfigurovat váš server tak, aby vracel následující hlavičky:
Hlavičky odpovědi API (https://api.example.com):
Access-Control-Allow-Origin: https://www.example.com
Content-Type: application/json
A můžete nakonfigurovat vaši webovou stránku (https://www.example.com) tak, aby používala následující hlavičku CSP:
Hlavička CSP webové stránky (https://www.example.com):
Content-Security-Policy: default-src 'self'; script-src 'self'; connect-src 'self' https://api.example.com;
Tato politika CSP umožňuje webové stránce načítat skripty a připojovat se k API, ale brání jí v načítání skriptů nebo připojování se k jiným doménám.
Závěr
Content Security Policy (CSP) a Cross-Origin Resource Sharing (CORS) jsou nezbytné nástroje pro posílení bezpečnosti vašich frontendových aplikací. Pečlivou konfigurací CSP a CORS můžete výrazně snížit riziko útoků XSS, útoků data injection a dalších bezpečnostních zranitelností. Nezapomeňte začít s restriktivní politikou, důkladně testovat a neustále sledovat a vylepšovat vaši konfiguraci, abyste se přizpůsobili změnám ve vaší aplikaci a vyvíjejícímu se prostředí hrozeb. Upřednostněním bezpečnosti frontendu můžete chránit své uživatele a zajistit integritu vašich webových aplikací v dnešním stále složitějším digitálním světě.